﻿using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace WpfApp1;

public class WeCheatDecrypt
{
    public static string Chk(string data)
    {
        if (data == null || data.Length <= 32)
        {
            return data;
        }

        string header = data.Substring(0, 32);
        string body = data.Substring(32);
        return header.ToUpper().Equals(CalculateMD5(body).ToUpper()) ? body : "";
    }

    public static string CalculateMD5(string input)
    {
        using (MD5 md5 = MD5.Create())
        {
            byte[] inputBytes = Encoding.ASCII.GetBytes(input);
            byte[] hashBytes = md5.ComputeHash(inputBytes);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hashBytes.Length; i++)
            {
                sb.Append(hashBytes[i].ToString("X2"));
            }
            return sb.ToString();
        }
    }
    
    public static string Decrypt(string data)
    {
        if (data == null || data.Length <= 1)
        {
            return "";
        }
        string result = data.Substring(1);
        result = Process(result);
        result = Encoding.UTF8.GetString(Convert.FromBase64String(result));
        return result;
    }

    private static string Process(string result)
    {
        int len = result.Length;
        List<int> indices;
        if (len < 4)
        {
            indices = new List<int>();
        }
        else if (len < 11)
        {
            indices = new List<int> { 0, 2 };
        }
        else
        {
            indices = CalculateIndicesNew(result, len);
        }
        return SwapCharacters(result, indices);
    }

    private static List<int> CalculateIndices(string result, int len)
    {
        int limit = Math.Min(4, (int)Math.Ceiling(len / 10.0));
        StringBuilder binaryString = new StringBuilder();
        for (int i = len - 1; i > len - 1 - limit; i--)
        {
            binaryString.Append(Convert.ToString(result[i], 2).PadLeft(4, '0'));
        }
        int offset = len - limit - 2;
        int offsetLength = offset.ToString().Length;
        List<int> indices = new List<int>();
        for (int i = 0; indices.Count < 10 && i + offsetLength < binaryString.Length; i += offsetLength)
        {
            int index = Convert.ToInt32(binaryString.ToString().Substring(i, offsetLength), 2);
            indices.Add(index % offset);
            index = Convert.ToInt32(binaryString.ToString().Substring(i + 1, offsetLength), 2);
            indices.Add(index % offset);
        }
        return indices;
    }
    
    public static List<int> CalculateIndicesNew2(string result, int len)
    {
        int limit = Math.Min(4, (int)Math.Ceiling(len / 10.0));
        string binaryString = "";
        for (int i = len - 1; i >= len - limit; i--)
        {
            // 将字符转换为其整数值，并转换为二进制字符串
            binaryString += Convert.ToString(result[i], 2).PadLeft(8, '0');
        }

        int offset = len - limit - 1;
        int offsetLength = offset.ToString().Length;
        List<int> indices = new List<int>();
        for (int i = 0; indices.Count < 10 && i + offsetLength <= binaryString.Length; i += offsetLength)
        {
            // 取子字符串并转换为十进制整数
            if (i + offsetLength <= binaryString.Length)
            {
                int index = Convert.ToInt32(binaryString.Substring(i, offsetLength), 2);
                indices.Add(index % offset);
            }
        }
        return indices;
    }
    
    private static List<int> CalculateIndicesNew(string result, int len)
    {
        int limit = Math.Min(4, (int)Math.Ceiling(len / 10.0));
        StringBuilder binaryString = new StringBuilder();
        for (int i = len - 1; i >= len - limit; i--)
        {
            // 获取字符的低8位（ASCII）并转换成二进制字符串
            string binValue = Convert.ToString(result[i] & 0xFF, 2).PadLeft(8, '0');
            // 将二进制字符串按四进制解析
            int value = BinaryToDecimal(binValue, 4);
            binaryString.Append(value);
        }

        int offset = len - limit - 2;
        int offsetLength = offset.ToString().Length;
        List<int> indices = new List<int>();
        for (int i = 0; indices.Count < 10 && i + offsetLength <= binaryString.Length; i += offsetLength)
        {
            if (i + offsetLength+1 > binaryString.Length) break;
            int index = int.Parse(binaryString.ToString().Substring(i, Math.Min(offsetLength, binaryString.Length - i)));
            indices.Add(index % offset);
            index = int.Parse(binaryString.ToString().Substring(i + 1, Math.Min(offsetLength, binaryString.Length - i)));
            indices.Add(index % offset);
        }
        return indices;
    }
    
    // Helper method to convert a binary string to a decimal number treating the binary as base-4
    private static int BinaryToDecimal(string binary, int baseToConvertTo)
    {
        int result = 0;
        int multiplier = 1;

        for (int i = binary.Length - 1; i >= 0; i--)
        {
            int digit = binary[i] - '0';
            result += digit * multiplier;
            multiplier *= baseToConvertTo;
        }

        return result;
    }

    private static string SwapCharacters(string result, List<int> indices)
    {
        char[] chars = result.ToCharArray();
        for (int i = indices.Count - 1; i >= 0; i -= 2)
        {
            for (int j = 1; j >= 0; j--)
            {
                char temp = chars[indices[i] + j];
                chars[indices[i] + j] = chars[indices[i - 1] + j];
                chars[indices[i - 1] + j] = temp;
            }
        }
        return new string(chars);
    }
    
}